using System.Collections.Generic;

namespace EternitySolver.Core
{
    public class Tile
    {
        public const int EDGE_TILE = 0;
        public int Top { get { return _layouts[_currentLayout].Top; } }
        public int Right { get { return _layouts[_currentLayout].Right; } }
        public int Bottom { get { return _layouts[_currentLayout].Bottom; } }
        public int Left { get { return _layouts[_currentLayout].Left; } }
        public int Number { get { return _number; } }

        private readonly List<TileOrientation> _layouts;
        private readonly int _number;
        private int _currentLayout;

        public Tile(int number, int top, int right, int bottom, int left)
        {
            _number = number;
            if (top == right && right == bottom && bottom == left && left == top) // all sides are the same
            {
                _layouts = new List<TileOrientation>(1) {new TileOrientation(this, top, right, bottom, left)};
            }
            else if (top == bottom && left == right) //rotationally symmetrical
            {
                _layouts = new List<TileOrientation>(2)
                               {
                                   new TileOrientation(this, top, right, bottom, left),
                                   new TileOrientation(this, left, top, right, bottom)
                               };
            }
            else //rotationally a-symmetrical
            {
                _layouts = new List<TileOrientation>(4)
                               {
                                   new TileOrientation(this, top, right, bottom, left),
                                   new TileOrientation(this, left, top, right, bottom),
                                   new TileOrientation(this, bottom, left, top, right),
                                   new TileOrientation(this, right, bottom, left, top)
                               };
            }
            _currentLayout = 0;
        }

        public void RotateToLayout(TileOrientation orientation)
        {
            _currentLayout = _layouts.FindIndex(obj => obj.Top == orientation.Top
                                                       && obj.Right == orientation.Right
                                                       && obj.Bottom == orientation.Bottom
                                                       && obj.Left == orientation.Left);
        }

        public IEnumerable<TileOrientation> Fits(TileSpecification specification)
        {
            foreach (TileOrientation layout in _layouts)
            {
                bool matchesTop = (specification.Top == null)
                                      ? (layout.Top != EDGE_TILE)
                                      : layout.Top == specification.Top;
                if (matchesTop)
                {
                    bool matchesRight = (specification.Right == null)
                                          ? (layout.Right != EDGE_TILE)
                                          : layout.Right == specification.Right;
                    if (matchesRight)
                    {
                        bool matchesBottom = (specification.Bottom == null)
                                              ? (layout.Bottom != EDGE_TILE)
                                              : layout.Bottom == specification.Bottom;
                        if (matchesBottom)
                        {
                            bool matchesLeft = (specification.Left == null)
                                                  ? (layout.Left != EDGE_TILE)
                                                  : layout.Left == specification.Left;
                            if (matchesLeft) yield return layout;
                        }
                    }
                }
            }
        }
    }
}